home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 2 / Assassins 2 - Ultimate Games No. 2 (1995)(Weird Science)[!][Amiga-CD32-CDTV].iso / arcade / jar / src / tetrissound.s < prev    next >
Text File  |  1995-01-01  |  34KB  |  1,275 lines

  1.  
  2.  
  3.     public    _stdout
  4.  
  5.  
  6. ; Simple Sound Engine © Copyright 1990 Software Alchemy All Rights Reserved
  7. ; Revision 0.70 Monday January 8 1990 Anselm Hook
  8. ; Revision 0.71 Jan 29 90
  9. ; Revision 0.80 Feb 2 90
  10.  
  11. ; Audio can be crunched by discarding the lowest 4 bits of data, and then
  12. ; overlapping the second half of the data with the first, although data is
  13. ; lost by this technique it still sounds pretty good.  I didn't do this here.
  14.  
  15. ;
  16. ; There are 2 bugs:
  17. ;
  18. ;    1) I am *still* losing serial data...
  19. ;       My current hypothesis is that the InternalSYNC routine is
  20. ;       breaking up packets despite theory to the contrary.
  21. ;       There is no fix for this except having a proper externally
  22. ;       supplied SYNC, if I do detect external SYNC I do turn mine off,
  23. ;       in which case it should work properly, although my keyboard
  24. ;       doesn't supply a sync to me.
  25. ;       [I am using a 256 byte circular buffer with raw serial input.]
  26. ;       search for the flag 'AZUREVIDIAN' to turn internal sync on.
  27. ;
  28. ;    2) Sounds do not get turned off quickly enough in StopSound and
  29. ;       as a consequence more channels are in use at any moment than
  30. ;       required, this gives a clipping effect to playback.  This doesn't
  31. ;       happen in the sequencer, but only in the playback routine.
  32. ;
  33. ;       Another problem is that the playback runs at level 6, which means
  34. ;       sound-interupts may not happen as quickly as possible.  I know
  35. ;       this causes a problem because when I had the level 6 just set a
  36. ;       flag, and ran the playback from non-interupt mode, it was flawless.
  37. ;       [Ie: sound-interupts also help stop sounds and free up channels].
  38. ;
  39. ;       You will notice the effect in the game music, it sounds like it
  40. ;       goes into solo mode for small sequences.
  41.  
  42.  
  43. ; Note I spell Interupt with one 'R', I forward this motion.
  44.  
  45. ;
  46. ; 64 Instruments currently, 16 Midi Channels (ie: 16 noises at any time-slice)
  47. ; NOTE:  Pass sound # to play in D0, must be multiple of 16.
  48. ; The MusicSequencer relys on an external MIDI SYNC.
  49. ; But the MusicEngine, which plays your finished product does its own timing.
  50. ;
  51.  
  52. ;
  53. ; I think the following two features would be nice to have,
  54. ; although I am not going to program them myself:
  55. ;
  56. ; #1)
  57. ; overlay mode erases any notes colliding with same channel at same sync time
  58. ;    overlay mode is good for final touch ups, and for multiple keyboards.
  59. ;    An entire music score could be built with one pass of the sequencer.
  60. ; #2)
  61. ; erase mode erases any notes on same channel right to end of sequence
  62. ;    erase mode is good for a single keyboard enviroment where multiple
  63. ;    passes of the sequencer (on diff tracks) are used to build a music score.
  64. ;
  65.  
  66.     blanks    on                ; Bezerk Aztek declarations
  67.  
  68. MIDI_NULL    equ $00                ; Supported Midi Commands
  69. MIDI_NOTE    equ $90
  70. MIDI_NOTEOFF    equ $A0
  71. MIDI_ENDSONG    equ $FC
  72. MIDI_SYNC    equ $F8
  73.  
  74. MIDI_FORCERTS    equ $ef                ; Internal Commands
  75.  
  76. MIDI_NOTECHANGE equ $B0                ; Unsupported Commands
  77. MIDI_CHANGESAM    equ $C0
  78. MIDI_SONGSTART    equ $FA
  79.  
  80.  
  81.  
  82. MAXSAM equ 64                    ; # of Instruments Maximum Allowed...
  83. BUFFERSIZE equ $20000                ; Memory of Music Score
  84.  
  85.  
  86.     public    SoundEngineStart        ; Warm up Audio Engine
  87.     public    SoundEngineStop            ; Stop Audio Engine
  88.     public    SoundPlay            ; Play Requested Sound D0>>4
  89.     public    SoundStop            ; Stop Requested Sound D0>>4
  90.  
  91.     public    SoundGetHunk
  92.     public    SoundDecodeHunk
  93.     public    SoundReleaseHunk
  94.  
  95.     public    MusicEngineStart
  96.     public    MusicEngineStop
  97.     public    MusicEnginePause
  98.     public    MusicEngineUnPause
  99.  
  100.     public    MusicSequencer
  101.  
  102.     public    JustPlayIt
  103.     public    StopTheMusic
  104.  
  105.  public Cases    ;(use for debugging "optimizations" )
  106.  public MCases
  107.  
  108.  
  109. ;**************************************************************************
  110. ; stand alone module, just compile and link to itself only, and run.
  111. StandAlone
  112.     clr.l    d0
  113. Borrow    lea    skipme(pc),a0            ;(flag, sequencer or player)
  114.     move.l    d0,(a0)
  115.  
  116.     lea    one(pc),a0
  117.     bsr    dumpmess
  118.     move.l    #BUFFERSIZE,d0
  119.     bsr    MusicMem            ; Get and Prep Mem
  120.     beq.s    StandX3
  121.  
  122.     lea    two(pc),a0
  123.     bsr    dumpmess
  124.     lea    FileName(pc),a0
  125.     bsr    SoundGetHunk            ; A0 = Pointer to File
  126.     beq.s    StandX2
  127.     lea    fh(pc),a1
  128.     move.l    a0,(a1)
  129.  
  130.     move.l    a0,-(a7)
  131.     lea    three(pc),a0
  132.     bsr    dumpmess
  133.     move.l    (a7)+,a0
  134.     bsr    SoundDecodeHunk            ; Decode from A0
  135.     beq.s    StandX
  136.  
  137.     lea    seven(pc),a0            ; say LOAD SCORE
  138.     bsr    dumpmess
  139.  
  140.     lea    FileName2(pc),a0
  141.     move.l    a0,d1
  142.     bsr    FindFileSize            ; d0 = size or zero
  143.     beq.s    noload
  144.     move.l    MusicBuffer(pc),a0
  145.     add.l    d0,a0
  146.     cmp.l    MusicBufferEnd(pc),a0        ; too big?
  147.     bcc.s    noload
  148.     lea    FileName2(pc),a1
  149.     move.l    a1,d1                ; D1 = Name
  150.     move.l    MusicBuffer(pc),a3        ; A3 = Dest
  151.     move.l    d0,a2                ; A2 = Size
  152.     move.l    d0,a5                ; (save size)
  153.     bsr    LoadFile
  154.     beq.s    noload
  155.     move.l    MusicBuffer(pc),a3        ; Advance to end of load
  156.     add.l    a5,a3
  157.     move.b    #MIDI_ENDSONG,(a3)+        ; Make sure we have a stop
  158.     move.b    #MIDI_ENDSONG,(a3)+        ; make sure stop is visible
  159.     move.b    #MIDI_ENDSONG,(a3)+
  160.     lea    BufferMerge(pc),a1        ; (dummy, flag merge)
  161.     move.l    a3,(a1)
  162.     lea    four(pc),a0            ; Say loaded
  163.     bsr    dumpmess
  164.     bra.s    load
  165. noload    move.l    MusicBuffer(pc),a3
  166.  
  167. load    lea    five(pc),a0
  168.     bsr    dumpmess
  169.  
  170.     move.l    skipme(pc),d0
  171.     bne    JustPlayItCont
  172.                         ; (A3 = End of Song IN & OUT)
  173.  
  174.  
  175.     btst    #7,$bfe001
  176.     bne.s    1$
  177. ;----------------------------------------------------------------------------
  178.     lea    didstartit(pc),a0        ; hack
  179.     move.b    #1,(a0)
  180.     bsr    SoundEngineStart        ; (playback only mode)
  181.     move.l    MusicBuffer(pc),a0
  182.     bsr    MusicEngineStart
  183.     moveq    #24,d0                ; Speed!
  184.     bsr    MusicEngineUnPause
  185. 0$    btst    #6,$bfe001
  186.     bne.s    0$
  187.     bsr    MusicEngineStop
  188.     bsr    SoundEngineStop
  189.     bra.s    StandX
  190. ;----------------------------------------------------------------------------
  191. 1$
  192.  
  193.  
  194. ;----------------------------------------------------------------------------
  195.     bsr    MusicSequencer            ; Play and allow sequencing
  196. ;----------------------------------------------------------------------------
  197.                         ; (A3 = End of Song IN & OUT)
  198.                         ; SAVE SCORE
  199.     sub.l    MusicBuffer(pc),a3
  200.     cmp.l    #20,a3                ; Don't save if very small
  201.     bcs.s    StandX
  202.     cmp.l    #BUFFERSIZE-3,a3        ; bug???
  203.     bcc.s    StandX
  204.     move.b    #MIDI_ENDSONG,(a3)+        ; Make sure we have a stop
  205.     move.b    #MIDI_ENDSONG,(a3)+        ; make sure stop is visible
  206.     move.b    #MIDI_ENDSONG,(a3)+
  207.     move.l    a3,a2                ; a2 = size
  208.     move.l    MusicBuffer(pc),a3        ; a3 = source
  209.     lea    FileName2(pc),a0
  210.     move.l    a0,d1                ; D1 = Name
  211.     bsr    SaveFile
  212.     lea    six(pc),a0
  213.     bsr    dumpmess
  214.  
  215. StandX    move.l    fh(pc),a1
  216.     bsr    SoundReleaseHunk
  217. StandX2    move.l    MusicBuffer(pc),a1
  218.     move.l    #BUFFERSIZE,d0
  219.     bsr    FreeMemory
  220. StandX3    moveq    #0,d0
  221.     rts
  222.  
  223. ;----------------------------------------------------------------------------
  224. JustPlayIt
  225.     bsr    SoundEngineStart        ; (always start audio at least)
  226.     moveq    #-1,d0
  227.     bra    Borrow                ; (either comes here or err)
  228. JustPlayItCont
  229.     lea    didstartit(pc),a0
  230.     move.b    #1,(a0)
  231.     move.l    MusicBuffer(pc),a0
  232.     bra    MusicEngineStart        ; Just play song (interupts)
  233. StopTheMusic
  234.     bsr    SoundEngineStop
  235.     move.b    didstartit(pc),d0        ; (allow game without music)
  236.     beq.s    nope
  237.     bsr    MusicEngineStop            ; stop interupts
  238.     bra    StandX
  239. nope    rts
  240. didstartit:
  241.     dc.l 0
  242. ;----------------------------------------------------------------------------
  243.  
  244.  
  245. FileName    dc.b    'music.hunk',0,0
  246.         even
  247. FileName2    dc.b    'music.score',0,0
  248.         even
  249. fh        dc.b    'ANDY HOOK '
  250. skipme        dc.l    0
  251.  
  252. ;**************************************************************************
  253.  
  254. SoundEngineStart
  255.     move.l    #$dff000,a6            ; A6 = Base of Hardware
  256.     lea    SoundVector(pc),a0
  257.     move.l    $70,(a0)            ; (save)
  258.     bsr    SoundEngineStop            ; (stop any previous activity)
  259.     lea    SoundInterupt(pc),a0        ; A0 = My Audio Handler
  260.     move.l    a0,$70                ; Audio Interupt Level 4
  261.     move.w    #$c780,$9a(a6)            ; Enable Audio Interupts
  262.     rts
  263.  
  264. SoundEngineStop
  265.     move.l    #$dff000,a6            ; A6 = Base of Hardware
  266.     move.w    #$000f,$96(a6)            ; Turn OFF All Audio DMA
  267.     move.w    #$0780,$9c(a6)            ; Clear Audio Interupts Pend
  268.     move.w    #$0780,$9a(a6)            ; Disable Audio Interupts
  269.     move.l    SoundVector(pc),$70        ; (restore)
  270.     bchg    #1,$bfe001            ; Audio Filter On/Off
  271.     rts
  272.  
  273.     dc.b    "As we become less like those we know, we "
  274.     dc.b    "seem to become more like those we hear of"
  275.  
  276. ;
  277. ; Sound Interupts occur only when its time to kill a sound
  278. ;
  279. SoundInterupt
  280.     move.w    #$2780,$dff09a            ; Prevent interupt collisions
  281.     movem.l    d0/d1/a0/a6,-(a7)
  282.     lea    $dff000,a6
  283.     move.w    $1e(a6),d0            ; Interupt Request Read
  284.     and.w    #$0780,d0
  285.     moveq    #0,d1
  286.     move.w    d0,d1                ; (save)
  287.      lsr.w    #7,d1
  288.     move.w    d1,$96(a6)            ; Stop these Audio DMA
  289.     bsr    SoundPause
  290.     move.w    d0,$9c(a6)            ; Clear these Audio Pending
  291.  
  292.     or.l    #$01000010,d1            ; Frequency Fast, Volume Low
  293.     lea    SoundChannel(pc),a0
  294.     btst    #0,d1
  295.     beq.s    1$
  296.     clr.b    (a0)
  297.     clr.b    4(a0)
  298.     move.l    d1,$a6(a6)
  299. 1$    btst    #1,d1
  300.     beq.s    2$
  301.     clr.b    1(a0)
  302.     clr.b    5(a0)
  303.     move.l    d1,$b6(a6)
  304. 2$    btst    #2,d1
  305.     beq.s    3$
  306.     clr.b    2(a0)
  307.     clr.b    6(a0)
  308.     move.l    d1,$c6(a6)
  309. 3$    btst    #3,d1
  310.     beq.s    4$
  311.     clr.b    3(a0)
  312.     clr.b    7(a0)
  313.     move.l    d1,$d6(a6)
  314. 4$
  315.     ;eor.w    #$8780,d0 (optional)
  316.     ;move.w    d0,$9a(a6)
  317.     move.w #$a780,$dff09a
  318.     movem.l    (a7)+,d0/d1/a0/a6
  319.     rte
  320.  
  321. ;
  322. ; Pointer to Audio Data
  323. ;
  324. SoundRaw    dc.l    0
  325. SoundVector    dc.l    0
  326.  
  327.  
  328. ;
  329. ; User List of available Sounds
  330. ; Format
  331. ;    Delta-Start.l, Length, Frequency, Volume, Priority, 0,0,0
  332. ;
  333. SoundList    dcb.w    16*MAXSAM,0
  334.  
  335. ;
  336. ; Sound Channel Arbitration Manager
  337. ;    x = Active Priority, 0 = Available
  338. ;
  339. SoundChannel    dc.b    0,0,0,0
  340. SoundOwner    dc.b    0,0,0,0
  341. SoundExtra    dc.b    0,0,0,0            ;<- Extra Info for Note-OFF
  342.         dc.b    0,0,0,0
  343. ;
  344. ;    Arbitration system finds best channel to free based on priority
  345. ;    of sound request.  Sounds of the same priority may overrun each other.
  346. ;    D0 = Requested Sound to Play
  347. ;    D7 = Off extra-information tag (optional)
  348. SoundPlay
  349.     move.w    #$2000,$dff09a            ; Allow Game Audio Also!!!
  350.     lea    SoundList(pc),a0
  351.     lea    (a0,d0.w),a0
  352.     move.l    6(a0),d5            ; Pre-get Frequency, Volume
  353.     moveq    #0,d7                ; (off tag defaults to zero)
  354.     bsr    SoundPlayTwo
  355.     move.w    #$a000,$dff09a
  356.     rts
  357.  
  358. SoundPlayTwo
  359.     tst.b    d5                ; Is Really Note Off?
  360.     beq    SoundStop
  361.     lea    SoundList(pc),a0
  362.     lea    (a0,d0.w),a0            ; A0 = Pointer to Sound Info
  363.     move.w    10(a0),d2            ; D2 = Request Priority
  364.     moveq    #3,d4                ; D4 = Channel # , Loop
  365.     moveq    #99,d3
  366. 1$    move.b    SoundChannel(pc,d4.w),d1    ; D1 = Channel Priority
  367.     beq.s    3$                ; Available Sound Channel?
  368.     cmp.b    d1,d2
  369.     bcs.s    2$
  370. ; cmp.b d2,d1
  371. ; bcc.s 2$
  372.     move.w    d4,d3                ; D3 = Last Available Priority
  373. 2$    dbf    d4,1$
  374.     cmp.b    #99,d3
  375.     beq.s    SoundPlay900            ; No Low Priority Slots Open
  376.     move.w    d3,d4
  377. 3$
  378.                         ; D4 = Channel #0-3
  379.     lea    SoundChannel(pc),a1
  380.     move.b    d2,(a1,d4.w)            ; D2 = New Sound Priority
  381.     move.b    d0,4(a1,d4.w)            ; D0 = New Sound BackPtr
  382.     move.b    d7,8(a1,d4.w)            ; D7 = Optional Off Tag
  383.     swap    d7
  384.     move.b    d7,12(a1,d4.w)
  385.     swap    d7
  386.  
  387.     moveq    #1,d0
  388.     lsl.w    d4,d0                ; D0 = Hardware Int # 1-2-4-8
  389.     move.w    d0,d1
  390.     lsl.w    #7,d1                ; D1 = (0-8)*128=Hardware DMA
  391.                         ; D0 = %0000000000001234
  392.                         ; D1 = %0000012340000000
  393.  
  394.     move.l    #$dff000,a6            ; A6 = Base of Hardware
  395.     move.w    d0,$96(a6)            ; Turn off Channel DMA
  396.     bsr    SoundPause            ; Delay against audio clicking
  397.     move.w    d1,$9a(a6)            ; Disable Int
  398.  
  399.     lea    $dff0a0,a2            ; A2 = Audio Hardware
  400.     lsl.w    #4,d4                ; 0-3 * 16
  401.     add.w    d4,a2
  402.  
  403.     ;move.l    SoundRaw(pc),a1            ; A1 = Base of Sound Data
  404.     ;add.l    (a0),a1
  405.     move.l    (a0),a1                ; (jan 29 90, offsets are precomputed now)
  406.  
  407.      move.l    a1,(a2)                ; Memory
  408.     move.w    4(a0),4(a2)            ; Length
  409.     move.l    d5,6(a2)            ; Frequency, Volume
  410.     bsr    SoundPause
  411.  
  412.     or.w    #$8000,d0
  413.     move.w    d0,$96(a6)            ; Re-enable DMA
  414.     bsr    SoundPause            ; (wait for started)
  415.                         ; 4(a2) Repeat can go here
  416.  
  417.     move.w    d1,$9c(a6)            ; Clear Started-Sound Flag
  418.     or.w    #$8000,d1
  419.     move.w    d1,$9a(a6)            ; Re-enable Interupt
  420. SoundPlay900
  421.     rts
  422.  
  423. SoundPause
  424.     move.l    d1,-(a7)            ; Time Delay to prevent clicks
  425.     move.w    #320,d1
  426. 1$    tst.b    d1
  427.     dbf    d1,1$
  428.     move.l    (a7)+,d1
  429.     rts
  430.  
  431.  
  432.  
  433. ;
  434. ;    Stop a requested sound, scans active sounds and stops if active
  435. ;        D0 = sound to stop
  436. ;        D7 = optional sentry/signature/tag/ID for more accurate off
  437. SoundStop
  438.     movem.l    d0-d3/a0/a6,-(a7)
  439.     lea    $dff000,a6
  440.                         ; D0 = Sound to stop
  441.     lea    SoundOwner(pc),a0
  442.     moveq    #3,d1                ; D1 = Loop Control
  443. 1$    cmp.b    (a0,d1.w),d0            ; D0 = Found Active Sound?
  444.     bne.s    2$
  445.     cmp.b    4(a0,d1.w),d7            ; Tags Match?
  446.     bne.s    2$
  447.     move.l    d7,d2
  448.     swap    d2
  449.     cmp.b    8(a0,d1.w),d2
  450.     bne.s    2$
  451.  
  452.     clr.b    -4(a0,d1.w)
  453.     clr.b    0(a0,d1.w)
  454.  
  455.     move.l    d1,d2
  456.     lsl.b    #4,d2                ; D2 = Channel Hardware
  457.     lea    $dff0a0,a1            ; A1 = Audio Hardware Base
  458.     move.w    #1,8(a1,d2.w)            ; Channel Volume (0 makes pop)
  459.     move.w    #100,6(a1,d2.w)            ; Period (0 makes click)
  460.  
  461.     moveq    #1,d2
  462.     lsl.b    d1,d2                ; D2 = Channel Bit #
  463.     move.w    d2,$96(a6)            ; Stop Audio
  464.     bsr    SoundPause
  465.     lsl.w    #7,d2
  466.     move.w    d2,$9c(a6)            ; Clear Interupt Pending
  467.  
  468. 2$    dbf    d1,1$
  469.     movem.l    (a7)+,d0-d3/a0/a6
  470. nyet:    rts
  471.  
  472. ;***************************************************************************
  473. ;***************************************************************************
  474. ; Music Engine written entirely in The Transform Language © 1990 Anselm Hook
  475. ; The Music Sequencer was tested using a YAMAHA SHS-10R Midi Synth Keyboard.
  476.  
  477. ;
  478. ; For those of you who are already freaked out by all the numbers:
  479. ;
  480. ; We had a bunch of hardware level stuff to setup the SoundEngine Interupts,
  481. ; Now we are going to setup a bunch more interupts for the MusicEngine so
  482. ; that it can keep track of time properly.  Aside from that the only other
  483. ; hardware stuff is the direct SERIAL I/O code....
  484. ;
  485.  
  486. ;
  487. ;  Simply load the music file up and pass start in a0
  488. ;  end must be terminated with a $fc
  489. ;
  490. MusicEngineStart
  491.                         ; a0 = the data!
  492.     lea    musicstart(pc),a1
  493.     move.l    a0,(a1)
  494.     lea    musicpos(pc),a1
  495.     move.l    a0,(a1)
  496.     rts
  497.  
  498. MusicEngineUnPause
  499.     move.b    didstartit(pc),d1
  500.     beq    nyet
  501.     lea    musicpos(pc),a0            ; Start/Restart Music
  502.     move.l    musicstart(pc),(a0)
  503.     lea    MusicServer(pc),a0
  504.     bra    TimerStartSpeed
  505.  
  506. MusicEngineStop
  507. MusicEnginePause
  508.     move.b    didstartit(pc),d1
  509.     beq    nyet
  510.     bra    TimerStop
  511.  
  512.  
  513. ;
  514. ;    MusicServer, an interupt driven routine which plays your music.
  515. ;
  516. MusicServer
  517.     btst    #1,$bfdd00            ; Clear INT_FLAG + Test Case
  518.     beq.s    MusicServer100
  519.     movem.l    d0-d7/a0-a6,-(a7)
  520.     bsr    MusicServerTwo
  521.     movem.l    (a7)+,d0-d7/a0-a6
  522. MusicServer100
  523.     move.w    #$2000,$dff09c            ; Clear interupt
  524.     rte
  525.  
  526. MusicServerTwo
  527.     lea    musicpos(pc),a0
  528.     move.l    (a0),a3
  529. Music3    move.b    (a3)+,d0
  530. Music4    move.b    d0,d1
  531.     and.w    #15,d1
  532.     lsr.b    #3,d0                ; 0-15 * 2
  533.     and.w    #30,d0
  534.     jmp    Cases(pc,d0.w)
  535. Cases    bra.s    Music3                ; #0
  536.     bra.s    Music3                ; #1
  537.     bra.s    Music3                ; #2
  538.     bra.s    Music3                ; #3
  539.     bra.s    Music3                ; #4
  540.     bra.s    Music3                ; #5
  541.     bra.s    Music3                ; #6
  542.     bra.s    Music3                ; #7
  543.     bra.s    Music3                ; #8
  544.     bra.s    Note                ; #9
  545.     bra.s    Music3                ; #10
  546.     bra.s    Music3                ; #11
  547.     bra.s    Music3                ; #12
  548.     bra.s    Music3                ; #13
  549.     rts                    ; #14    FORCE RTS
  550. Sync    cmp.b    #12,d1                ; #15   END?
  551.     bne.s    1$
  552.     move.l    musicstart(pc),a3
  553. 1$    lea    musicpos(pc),a0
  554.     move.l    a3,(a0)
  555.     rts
  556.  
  557. ;---------------------------------------------------------------------------
  558. periods    dc.w 856,808,760,720,680,640,604,572,540,508,480,452,428,404,380,360
  559.     dc.w 340,320,302,286,270,254,240,226,214,202,190,180,170,160,151,143
  560.     dc.w 135,127,120,113,107,101
  561. ;---------------------------------------------------------------------------
  562.  
  563. Note    add.b    d1,d1                ; d1 = midi channel 0-15
  564.     move.w    instr(pc,d1.w),d6        ; D6 = Instr of Channel 0-15
  565.     move.b    -1(a3),d7            ; Signature for Accurate OFF
  566. NoteTwo    move.b    (a3)+,d0            ; D0 = Note #0-x
  567.     cmp.b    #$35+64,d0
  568.     bcc.s    Music4
  569.     sub.b    #$35,d0                ; Yamaha Lowest Key #
  570.     swap    d7
  571.     move.b    d0,d7                ; construct signature id.w
  572.     swap    d7                ; made of command,channel,note
  573.  
  574.     add.b    d0,d0
  575.     move.w    periods(pc,d0.w),d5        ; D5 =Note=Rate(in upper word)
  576.     swap    d5
  577.     move.b    (a3)+,d5            ; D5 = Vol %xxxxxxxxxx111111
  578.  lsr.b #1,d5            ; music volume to half, yamaha only!!!
  579.     move.w    d6,d0
  580.  
  581.     bsr    SoundPlayTwo            ; Don't corrupt d6/a3-a7
  582.     bra.s    NoteTwo                ; Any more events in packet?
  583.  
  584. ;---------------------------------------------------------------------------
  585. instr    dc.w    0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240
  586.     ;dc.w    256,17*16,18*16,19*16,20*16,21*16,22*16,23*16,24*16,25*16
  587.     ;dc.w    26*16,27*16,28*16,29*16,30*16,31*16
  588. ;---------------------------------------------------------------------------
  589.  
  590. NoteChange
  591.     add.b    d1,d1                ; Channel 0-15
  592.     move.b    (a3)+,d0            ; Instr # 0-x
  593.     lsl    #4,d0                ; *16 to for SoundPlay format
  594.     lea    instr(pc),a0
  595.     move.b    d0,(a0,d1.w)
  596.     bra.s    Music3
  597.  
  598. musicpos    dc.l    0
  599. musicstart    dc.l    0
  600.  
  601. ;************************************************************************
  602. ;************************************************************************
  603. ; Utilities for use with music engine
  604.  
  605. ;
  606. ; Music sequencer:
  607. ;    RMB  -  Restart Music - Will merge your music with previous score.
  608. ;    LMB  -  Exit, saves music to disk
  609. ;
  610.  
  611.  
  612. ;Sequencer theory:
  613. ;
  614. ;Sequencer - Switch thru midi-events
  615. ;    (get-events)
  616. ;    note-on
  617. ;        play, store
  618. ;    pulse
  619. ;        read bufferA till pulse
  620. ;            play,store (overlay/erase mode)
  621. ;        write pulse
  622. ;
  623. ;play  - call music player manually.
  624. ;store - write bufferB
  625. ;
  626.  
  627.  
  628. ;************************************************************************
  629. MusicSequencer
  630.     bsr    MusicRestart
  631.     bsr    SerialStart
  632.     bsr    SoundEngineStart
  633.     lea    InternalSync(pc),a0
  634.     bsr    TimerStart
  635.     bsr    MusicIn
  636.     bsr    TimerStop
  637.     bsr    SoundEngineStop
  638.     bra    SerialStop
  639. ;************************************************************************
  640.  
  641.  
  642. ;************************************************************************
  643. ;
  644. ;    Music In Store, main routine
  645. ;        Watches for user restart/quit input
  646. ;        Reads raw-serial data, plays and stores it (till sync)
  647. ;        Upon sync, merges in old data
  648. ;        adds sync and loops...
  649. ;
  650. Unknown
  651. MusicIn
  652.     btst    #6,$bfe001            ; LMB
  653.     bne.s    1$
  654.     rts
  655. 1$    btst    #7,$bfe001            ; RMB  (#6 is port #2 bytheway)
  656.     bne.s    2$                ; (remember to refresh sensors)
  657. 0$    move.w    #$ff0,$dff180            ; YELLOW
  658.     btst    #7,$bfe001            ; (must release also)
  659.     beq.s    0$
  660.     bsr    MusicRestart
  661. 2$    bsr    MidiIn                ; Wait for Midi Event
  662. MusIn2    move.b    d0,d1                ; D1 = Channel + Command
  663.     lsr.b    #3,d0                ; D0 = Command
  664.     and.w    #30,d0
  665.     jmp    MCases(pc,d0.w)
  666. MCases    bra.s    Unknown
  667.     bra.s    Unknown
  668.     bra.s    Unknown
  669.     bra.s    Unknown
  670.     bra.s    Unknown
  671.     bra.s    Unknown
  672.     bra.s    Unknown
  673.     bra.s    Unknown
  674.     bra.s    Unknown
  675.     bra.s    MNote                ; #9
  676.     bra.s    Unknown                ; #10
  677.     bra.s    Unknown                ; #11
  678.     bra.s    Unknown                ; #12
  679.     bra.s    Unknown                ; #13
  680.     bra.s    Unknown                ; #14
  681.     bra    MSync                ; #15
  682. ;
  683. ; Store and play user input
  684. ;
  685. MNote    cmp.l    MusicBufferEnd(pc),a3
  686.     bcc.s    MEnd
  687.  
  688. ; within this sync I can receive any other packet
  689. ; or more of these (notes)
  690. ; if I do not recognize the packet I should pass it back to the
  691. ; main routine for it to determine the packet type.
  692.  
  693.     bsr    MidiIn                ; D0 = Note #
  694.     cmp.b    #$35,d0                ; Not my packet
  695.     bcs.s    MusIn2
  696.     cmp.b    #$35+64,d0            ; Not my packet
  697.     bcc.s    MusIn2
  698.     move.b    d0,d2
  699.     bsr    MidiIn                ; D0 = Volume
  700.     cmp.b    #$41,d0                ; Transmission bug???
  701.     bcc.s    MusIn2
  702.  
  703.     tst.b    d1                ; Command+Channel (once only)
  704.     beq.s    1$
  705.     move.b    d1,d7                ; D7 = Off Signature, dont hurt me!
  706.     move.b    d1,(a3)+
  707.     and.w    #15,d1
  708.     add.b    d1,d1
  709.     lea    instr(pc),a0
  710.     move.w    (a0,d1.w),d6            ; D6 = Instrument # (dont damage)
  711. 1$    clr.b    d1
  712.  
  713. ; whenever we play a note it goes to one of the four channels, now we are
  714. ; going to pass a note off for that note, but we may inadvertantly be turning
  715. ; off another note which happens to be using that channel dma.  To actually
  716. ; turn off the proper note we must be able to positively identify that
  717. ; particular note and midi source channel.
  718.  
  719. ; so remembering a sound involves remembering its host frequency and channel.
  720. ;
  721. ; whenever we do a midi-change to a specific channel we must clear all note
  722. ; offs for that channel; so that a note off for an old instrument doesn't
  723. ; affect any new ones.
  724. ;
  725.     move.b    d2,0(a3)            ; Note #0-x
  726.     move.b    d0,1(a3)            ; Volume
  727.     move.b    #MIDI_FORCERTS,2(a3)        ; (return to me)
  728.     move.w    d1,-(a7)
  729.     bsr    NoteTwo                ; A3+=3, PASS D6!!!
  730.     move.w    (a7)+,d1
  731.     subq.w    #1,a3                ; Delete FORCE_RTS
  732.     bra.s    MNote
  733.  
  734. MEnd    move.w    #$f00,$dff180
  735.     bra    MusicIn
  736.  
  737.  
  738. ;
  739. ; We've played user input, now merge in old score (of this sync).
  740. ;
  741. ; We install a fake handler and pass old data as fresh input
  742. ; The full capacity of the MusicSequencer can be applied to old data now.
  743. ; The only thing we do is catch the old sync and abort at that time.
  744. ; (Thus the old data timing is run off new external syncs also)
  745. ;
  746. MSync    move.w    #$ff01,$dff034            ; Hardware Refresh for RMB
  747.     cmp.b    #$f8,d1
  748.     bne    Unknown
  749.     cmp.l    MusicBufferEnd(pc),a3
  750.     bcc.s    MEnd
  751.     lea    ReadFn(pc),a0            ; On pass #2?
  752.     lea    Sinking(pc),a1
  753.     cmp.l    (a0),a1
  754.     beq.s    MSync2
  755.     move.l    (a0),4(a0)            ; Save Old Fn
  756.     move.l    a1,(a0)
  757.     bra    MusicIn                ; Eat Fake Events till SYNC
  758. MSync2    move.l    4(a0),(a0)
  759.     move.b    #MIDI_SYNC,(a3)+
  760.     bra    MusicIn
  761. Sinking    move.b    #MIDI_SYNC,d0
  762.     cmp.l    a3,a4                ; New Overran Old ???
  763.     bcs.s    SyncHit
  764.     cmp.l    MusicBufferEnd(pc),a4        ; Read Hit end
  765.     bcc.s    SyncHit
  766.     move.b    (a4)+,d0            ; Read Old Music
  767. SyncHit    rts
  768.  
  769. MidiIn    move.l    ReadFn(pc),a0
  770.     jmp    (a0)
  771. ;***********************************************************************
  772.  
  773.     dc.b    "When you find yourself between  "
  774.     dc.b    "the Devil and the deep blue sea "
  775.  
  776. MusicRestart
  777.     lea    ReadFn(pc),a0
  778.     lea    SerialInWait(pc),a1
  779.     move.l    a1,(a0)
  780.  
  781.     move.l    BufferMerge(pc),a0        ; First Time?
  782.     cmp.l    #0,a0
  783.     beq.s    UseOld
  784.  
  785. ; a single buffer has the source being copied back to the dest.
  786. ; the trick is that the source must start suitably far away from the dest.
  787. ; as a matter of fact the best possible place for the source to be is as
  788. ; close to the very end as possible, so overwrite happens last if possible.
  789.  
  790.     move.l    MusicBuffer(pc),a1
  791.     move.l    MusicBufferEnd(pc),a0
  792.     cmp.l    a3,a1
  793.     beq.s    2$
  794. 1$    move.b    -(a3),-(a0)            ; Copy up to end...
  795.     cmp.l    a3,a1
  796.     bcs.s    1$                ; A3 will equal *MusicBuffer
  797. 2$    move.l    a0,a4                ; A4 = SOURCE, A3 = DEST
  798. 4$    cmp.l    a1,a0
  799.     bcc.s    3$
  800.     move.b    #MIDI_SYNC,-(a0)        ; (Erase Rest of Buffer)
  801.     bne.s    4$
  802. 3$    bra.s    Neateh
  803.  
  804. UseOld    move.l    MusicBufferEnd(pc),a4        ; A4 = Tracks SOURCE (default)
  805. Neateh    move.l    MusicBuffer(pc),a3        ; A3 = Tracks DEST
  806.     lea    BufferMerge(pc),a0
  807.     move.l    a4,(a0)
  808.     rts
  809.  
  810.  
  811. MusicMem
  812.     move.l    d0,a2
  813.     bsr    AllocateMemory
  814.     beq.s    MusicMemFail
  815.     move.l    d0,d1
  816.     add.l    a2,d1
  817.     lea    MusicBuffer(pc),a0
  818.     move.l    d0,(a0)+            ; (start/end)
  819.     sub.l    #10,d1                ; for checking if *near* end
  820.     move.l    d1,(a0)
  821.     move.l    d0,a0
  822.     move.b    #MIDI_SYNC,d0            ; Prepare recording buffer
  823. 1$    move.b    d0,(a0)+
  824.     cmp.l    a0,d1
  825.     bne.s    1$
  826.     moveq    #1,d0
  827. MusicMemFail
  828.     rts
  829.  
  830. ReadFn        dc.l    0,0
  831. MusicBuffer    dc.l    0            ; Start both buffers
  832. MusicBufferEnd    dc.l    0            ; End of both buffers
  833. BufferMerge    dc.l    0            ; Start of Source buffer
  834.  
  835. ;****************************************************************************
  836. ;****************************************************************************
  837.  
  838.     ;some serial in stuff i don't set:
  839.     ;move.w    #115,$dff032            ; BAUD = 31250
  840.     ;bclr    #6,$bfde00            ; CIAB, SPMODE=Input
  841.     ;move.b    #3,$bfd200            ; MODE = Input
  842.     ;move.b    #$ff,$bfd000            ; Turn on everything...
  843.  
  844. SerialOut
  845.     move.w    #115,$dff032            ; BAUD = 31250
  846.     move.b    #$c0,$bfd200            ; MODE = Output
  847.     move.b    #0,$bfd000
  848. 1$    btst    #13-8,$dff018            ; Buffer Ready?
  849.     beq.s    1$
  850.     move.w    d0,$dff030            ; Output new byte
  851.     rts
  852.  
  853. SerialInWait
  854.     move.w    d1,-(a7)
  855.     lea    SerialPos(pc),a0
  856.  
  857.     move.w    (a0),d1                ; My Read Pos
  858. SWait    move.b    3(a0),d0            ; Sync Timer Interupt Pos
  859.     cmp.b    d1,d0                ; Caught up, wait for more
  860.     beq.s    AddSync
  861.  
  862.     move.b    4(a0,d1.w),d0            ; D0 = Value to Return
  863.  
  864.     cmp.b    #MIDI_SYNC,d0            ; External SYNC found!!!
  865.     bne.s    1$
  866.     move.w    #80,-4(a0)            ; Disable internal SYNCing
  867. 1$    tst.w    -4(a0)
  868.     beq.s    2$
  869.     subq.w    #1,-4(a0)            ; Try to enable...
  870.  
  871. 2$    addq.b    #1,d1                ; Add molulo 255
  872.     move.b    d1,1(a0)            ; Store modulo 255
  873.     move.w    (a7)+,d1
  874.     rts
  875.  
  876.  
  877. AddSync
  878.     bra.s    SWait                ; AZUREVIDIAN (remove me)
  879.     tst.w    -4(a0)                ; Externally overriden?
  880.     bne.s    SWait
  881.     tst.w    -2(a0)
  882.     beq.s    SWait
  883. 4$    subq.w    #1,-2(a0)
  884.     move.b    #MIDI_SYNC,d0
  885.     move.w    (a7)+,d1
  886.     rts
  887.  
  888. ;
  889. ; the theory for internal syncs is that the midi-device should dump data
  890. ; in packets, such that serialwait should never wait for the rest of a packet
  891. ; If this is true then serialwait only waits during interm periods between
  892. ; packets.  This is a safe time to issue a sync without breaking packets.
  893. ;
  894. ; In reality I get so many syncs that they just about override everything
  895. ; else.
  896. ;
  897.  
  898. SerialInterupt
  899.     btst    #11-8,$dff01c            ; My Interupt?
  900.     beq.s    2$
  901.  
  902.     movem.l    d0/d1/a0,-(a7)
  903.     move.w    $dff018,d0            ; Read Byte from Hardware
  904.     lea    SerialPos(pc),a0        ; Circular buffer
  905.     move.w    2(a0),d1            ; Get Buffer Pointer, clean.w
  906.     move.b    d0,4(a0,d1.w)            ; Store data byte to buffer
  907.     addq.b    #1,d1                ; Advance pointer Modulo 255
  908.     move.b    d1,3(a0)            ; store pointer Modulo 255
  909.     movem.l    (a7)+,d0/d1/a0
  910.  
  911. 2$    move.w    #$0800,$dff09c            ; Clear INTF_RBF in INTREQ
  912.     rte
  913.         dc.w    0            ; Sync Disable Time Flag
  914.         dc.w    0            ; Sync Flag
  915. SerialPos    dc.w    0,0            ; Ptr #2,#3
  916.         dcb.l    256/4,0            ; Serial Buffer
  917.  
  918. ;****************************************************************************
  919.  
  920. SerialStart
  921.     move.w    #$0800,$dff09a
  922.     move.w    #115,$dff032            ; BAUD = 31250
  923.     lea    SerialVector(pc),a0
  924.     move.l    $74,(a0)            ; Save Old Vector
  925.     lea    SerialInterupt(pc),a0
  926.     move.l    a0,$74
  927.     move.w    #$0800,$dff09c            ; Clear any previous
  928.     move.w    #$c800,$dff09a            ; Turn on Serial Interupt
  929.     rts
  930.  
  931. SerialStop
  932.     move.w    #$0800,$dff09a
  933.     lea    SerialVector(pc),a0
  934.     move.l    (a0),$74
  935.     rts
  936. SerialVector    dc.l    0
  937.  
  938. ;****************************************************************************
  939.  
  940. InternalSync
  941.     btst    #1,$bfdd00            ; Mine?
  942.     beq.s    0$
  943.  
  944.     move.l    a0,-(a7)
  945.     lea    SerialPos(pc),a0
  946.     addq.w    #1,-2(a0)            ; One More Sync!!!
  947.     move.l    (a7)+,a0
  948.  
  949. 0$    move.w    #$2000,$dff09c
  950.     rte
  951.  
  952. ;************************************************************************
  953. ;
  954. ; A0 = Handler function, must turn on yourself (poke $dff09a,$8000+$2000)
  955. ;
  956. TimerStart
  957.     moveq    #24,d0                ; Speed!
  958. TimerStartSpeed
  959.     move.w    #$2000,$dff09a            ; Disable external interupt
  960.     lea    TimerVector(pc),a1
  961.     move.l    $78,(a1)
  962.     move.l    a0,$78                ; Set up new interupt server
  963.     lea    $bfd000,a1
  964.     move.b    #$7f,$d00(a1)            ; Disable CIAB interupt
  965.     move.b    #204,$400(a1)            ; TimerA for 1 millisecond
  966.     move.b    #2,$500(a1)
  967.     move.b    d0,$600(a1)            ; TimerB for x milliseconds
  968.     move.b    #0,$700(a1)
  969.     move.b    #$01,$e00(a1)            ; TimerA continuous
  970.     move.b    #$41,$f00(a1)            ; TimerB continuous,count A
  971.     move.b    #$82,$d00(a1)            ; Enable TimerB interupt
  972.     move.w    #$2000,$dff09c            ; Clear Interupt
  973.     move.w    #$e000,$dff09a            ; Enable external interupt
  974.     rts
  975.  
  976. TimerStop
  977.     move.w    #$2000,$dff09a            ; Disable external interupt
  978.     move.l    TimerVector(pc),$78        ; Restore old timer handler
  979.     move.b    #0,$bfde00            ; TimerA continuous
  980.     move.b    #0,$bfdf00            ; TimerB continuous
  981.     move.w    #$2000,$dff09c            ; Clear Interupt
  982.     move.w    #$a000,$dff09a            ; Enable external Interupt
  983.     rts
  984.  
  985. TimerVector:    dc.l    0
  986.  
  987. ;****************************************************************************
  988. ;****************************************************************************
  989.  
  990. ;
  991. ; FORMAT
  992. ;    'SAND' , # of Sample.w, # Size of header.w,
  993. ;    [ HEADER.l ] * # Size of header  (including 'SAND' Sentry ID).
  994. ;    [ SAMPLES ]  (whatever memory they take)
  995. ;
  996.  
  997. ; I am currently forcing only 16 samples, because of hardcoded memory space.
  998.  
  999. SoundDecodeHunk
  1000.     cmp.l    #'SAND',(a0)
  1001.     bne.s    DecodeFail
  1002.     move.w    4(a0),d0            ; # = Samples
  1003.     cmp.w    #999,d0
  1004.     bcc    DecodeFail
  1005.     move.w    6(a0),d1            ; # = Size of Header
  1006.     cmp.w    #999,d0
  1007.     bcc    DecodeFail
  1008.  
  1009.     lsl.w    #2,d1                ; * 4 (get longwords)
  1010.     move.l    a0,a1
  1011.     addq.w    #8,a0                ; A0 = Start of Offsets
  1012.     add.w    d1,a1                ; A1 = Start of Data
  1013.  
  1014.     lea    SoundList(pc),a2        ; A2 = DEST  (List to Build)
  1015.  
  1016.     cmp.w    #MAXSAM,d0            ; Allow 64 Samples Max, 1 Min
  1017.     bcs.s    1$
  1018.     moveq    #MAXSAM,d0
  1019. 1$    subq.w    #1,d0
  1020.     bmi.s    DecodeFail
  1021.  
  1022. 2$    move.l    a1,d1                ; START + OFFSET = RAW DATA ADDRESS
  1023.     move.l    (a0)+,d2            ; Delta Start
  1024.     move.l    (a0),d3                ; Delta End
  1025.     add.l    d2,d1
  1026.     sub.l    d2,d3
  1027.     lsr.w    #1,d3
  1028.  
  1029.     move.l    d1,(a2)                ; Start
  1030.     move.w    d3,4(a2)            ; Length in words
  1031.     move.w    #214,6(a2)            ; Frequency
  1032.     move.w    #64,8(a2)            ; Volume
  1033.     move.w    #2,10(a2)            ; Priority
  1034.     move.w    #0,12(a2)            ; (pad)
  1035.     move.w    #0,14(a2)            ; (pad)
  1036.  
  1037.     add.w    #16,a2                ; Next Sample
  1038.  
  1039.     dbf    d0,2$
  1040.     moveq    #1,d0
  1041.     rts
  1042. DecodeFail
  1043.     moveq    #0,d0
  1044.     rts
  1045.  
  1046.  
  1047. ; The Go Anywhere Loader
  1048. ; You might find the following useful, its a forget-about-memory-management
  1049. ; file loading subroutine, you just pass it the name and it returns to you
  1050. ; a pointer to the start.  When exiting you call ReleaseFile (with the
  1051. ; same pointer you got earlier) , which just frees up the memory that it used
  1052. ; I finally decided that I needed a permanent utility like this...
  1053. ;***************************************************************************
  1054. ;***************************************************************************
  1055.  
  1056. LVODelay    equ -30-168
  1057. LVODeviceProc    equ -30-144
  1058. LVOSeek        equ -30-36
  1059. LVOOutput    equ -30-30
  1060. LVOInput    equ -30-24
  1061. LVOOpen        equ -30
  1062. LVOWrite    equ -30-18
  1063. LVORead        equ -30-12
  1064. LVOClose    equ -30-6
  1065. LVOLock        equ -$54
  1066. LVOUnLock    equ -$5A
  1067. LVOExamine    equ -$66
  1068. LVOOpenLibrary    equ -408
  1069. AllocMem    equ -30-168
  1070. FreeMem        equ -30-180
  1071. AllocAbs    equ -30-$cc
  1072.  
  1073. ;***********************************************************************
  1074. ;***********************************************************************
  1075. ;
  1076. ; GetFile, Load a file, return pointer to memory, this is a generic utility
  1077. ;    Passed
  1078. ;        A0 = File Name
  1079. ;    Returns
  1080. ;        A0 = Pointer to Start, (Save this Pointer for Close Down)
  1081. ;
  1082. LoadScore
  1083. SoundGetHunk
  1084. GetFile
  1085.     move.l    a0,a3
  1086.     bsr    GetDosBase            ; A6 = Dos Base *** 
  1087.     move.l    a3,d1                ; D1 = File Name to Examine
  1088.     bsr.s    FindFileSize            ; D0 = File Size
  1089.     beq.s    GetFailure
  1090.     addq.l    #4,d0                ; +4 for internal header
  1091.     move.l    d0,a2                ; A2 = Internal Size
  1092.     bsr    AllocateMemory            ; Pass D0=FileSize, return D0=Mem
  1093.     beq.s    GetFailure
  1094.     move.l    a3,d1                ; D1 = File Name to Load
  1095.     move.l    d0,a3                ; A3 = Start
  1096.     move.l    a2,(a3)+            ; A2 = Size (hide it for later freeing)
  1097.     bsr    LoadFile
  1098.     beq    ReleaseFile
  1099.     move.l    a3,a0                ; Success
  1100.     moveq    #1,d0
  1101. GetFailure
  1102.     rts
  1103.  
  1104. ;***********************************************************************
  1105. ;
  1106. ; ReleaseFile, generic utility to work in conjunction with GetFile
  1107. ;    Passed
  1108. ;        A1 = Pointer to GetFile Handle on file
  1109. ReleaseScore
  1110. SoundReleaseHunk
  1111. ReleaseFile
  1112.     move.l    -(a1),d0            ; D0 = Get Header, Size to Release
  1113.     bsr    FreeMemory    
  1114.     moveq    #0,d0                ; (return as failure always)
  1115.     rts
  1116. ;***********************************************************************
  1117. AllocateMemory
  1118.                         ; D0 = Amount
  1119.     move.l    #2,d1                ; chip only
  1120.     move.l    a6,-(a7)
  1121.     move.l    4,a6                ; Exec base
  1122.     jsr    AllocMem(a6)
  1123.     move.l    (a7)+,a6
  1124.     tst.l    d0
  1125.     rts
  1126. ;***********************************************************************
  1127. FreeMemory
  1128.                         ; A1 = Where, D0 = Amount
  1129.     move.l    a6,-(a7)
  1130.     move.l    4,a6
  1131.     jsr    FreeMem(a6)
  1132.     move.l    (a7)+,a6
  1133.     rts
  1134. ;***********************************************************************
  1135. ;***********************************************************************
  1136. ;
  1137. ; Returns A6 = DosBase (I *know* that this will never fail)
  1138. ;
  1139. GetDosBase
  1140.     move.l    4,a6                ; Open DOS.LIBRARY
  1141.     lea    DosName(pc),a1
  1142.     moveq    #0,d0                ; (any rev #)
  1143.     jsr    LVOOpenLibrary(a6)
  1144.     move.l    d0,a6                ; A6 = DOS.LIBRARY
  1145.     rts
  1146. ;***********************************************************************
  1147. ;***********************************************************************
  1148. ;
  1149. ; LoadFile, a generic utility
  1150. ;    Passed
  1151. ;        D1=NAME, A3=DEST, A2=SIZE
  1152. ;    Returns
  1153. ;        success=1/fail=0
  1154. ;
  1155. LoadFile
  1156.     movem.l    d1/a2/a3,-(a7)
  1157.     bsr    GetDosBase
  1158.     movem.l    (a7)+,d1/a2/a3
  1159.                         ; D1 = Get FileName
  1160.     move.l    #1005,d2            ; D2 = MODE_OLDFILE  LOAD
  1161.     jsr    LVOOpen(a6)            ; Open the file
  1162.     move.l    d0,d4                ; d4 is reserved as file ptr
  1163.     beq    LoadFailure
  1164.     move.l    a3,d2                ; D2 = Start
  1165.     move.l    a2,d3                ; D3 = Size
  1166.     move.l    d4,d1                ; D1 = File Pointer
  1167.     jsr    LVORead(a6)
  1168.     move.l    d4,d1                ; FP
  1169.     jsr    LVOClose(a6)            ; Close File
  1170.     moveq    #1,d0                ; Success
  1171. LoadFailure
  1172.     rts
  1173. ;***********************************************************************
  1174. ;***********************************************************************
  1175. ;    D1=NAME, A3=SOURCE, A2=SIZE
  1176. SaveFile
  1177.     movem.l    d1/a2/a3,-(a7)
  1178.     bsr    GetDosBase
  1179.     movem.l    (a7)+,d1/a2/a3
  1180.     move.l    #1006,d2            ; D2 = MODE_NEWFILE SAVE
  1181.     jsr    LVOOpen(a6)            ; Open the file
  1182.     move.l    d0,d4                ; d4 is reserved as file ptr
  1183.     beq    LoadFailure
  1184.     move.l    a3,d2                ; D2 = Start
  1185.     move.l    a2,d3                ; D3 = Size
  1186.     move.l    d4,d1                ; D1 = File Pointer
  1187.     jsr    LVOWrite(a6)
  1188.     move.l    d4,d1                ; FP
  1189.     jsr    LVOClose(a6)            ; Close File
  1190.     moveq    #1,d0                ; Success
  1191.     rts
  1192.  
  1193. ;***********************************************************************
  1194. ;***********************************************************************
  1195. ;
  1196. ;  Find the size of a file, a generic utility
  1197. ;    Passed
  1198. ;        D1 = Pointer to File Name (may have to be longword aligned)
  1199. ;    Returns
  1200. ;        D0 = Size of File or 0.
  1201. ;
  1202. ;LVOLock    equ -$54
  1203. ;LVOUnLock    equ -$5A
  1204. ;LVOExamine    equ -$66
  1205. ;LVOOpenLibrary    equ -408
  1206. ;
  1207.  
  1208. FindFileSize
  1209.                         ; D1 = File Name to Examine
  1210.     moveq    #-2,d2
  1211.     jsr    LVOLock(a6)            ; D1=Name,D2=Mode
  1212.     move.l    d0,d4
  1213.     beq.s    Failure
  1214.     lea    FileInfoBlock(pc),a2
  1215.  
  1216.     move.l    a2,d0                ; manually force long word alignment
  1217.     btst    #1,d0               ; (i'm not sure if this is necessary but...)
  1218.     beq.s    1$
  1219.     addq.w #2,a2
  1220. 1$
  1221.     move.l    a2,d2
  1222.     move.l    d4,d1
  1223.     jsr    LVOExamine(a6)            ; D1=Lock,D2=FIB
  1224.     move.l    d0,-(a7)
  1225.     move.l    d4,d1
  1226.     jsr    LVOUnLock(a6)            ; D1=Lock
  1227.     move.l    (a7)+,d0
  1228.     beq.s    Failure
  1229.     move.l    $007C(a2),d0            ; D0 = Size of File
  1230.     rts
  1231. Failure    moveq    #0,d0                ; D0 = Failure
  1232.     rts
  1233.  
  1234. DosName:    dc.b    'dos.library',0
  1235.         even
  1236. ;;;        cnop    0,4            ; Longword Aligned 
  1237. ;;;                        ; (actually this may load wrong)
  1238. FileInfoBlock    dcb.b    268+2,0
  1239.  
  1240. ;***********************************************************************
  1241. ;***********************************************************************
  1242.  
  1243.  
  1244. dumpmess
  1245.     movem.l    d0-d7/a0-a6,-(a7)
  1246.     moveq    #0,d3
  1247.     move.b    (a0)+,d3            ; D3 = Length
  1248.     move.l    a0,d2                ; D2 = What
  1249.     bsr    GetDosBase
  1250. ;    jsr    LVOOutput(a6)            ; Get LVOOutput Handle
  1251. ;    move.l    d0,d1                ; D1 = Output Handle
  1252.     move.l    _stdout(pc),d1
  1253.     beq.s    dumpnot
  1254.     jsr    LVOWrite(a6)            ; LVOWrite
  1255.     movem.l    (a7)+,d0-d7/a0-a6
  1256. dumpnot
  1257.     rts
  1258.  
  1259. one    dc.b    64-24,'Sequencer attempting to allocate memory',10,0
  1260.     even
  1261. two    dc.b    64-24,'Sequencer attempting to load music.hunk',10,0
  1262.     even
  1263. three    dc.b    66-24,'Sequencer attempting to decode music.hunk',10,0
  1264.     even
  1265. four:    dc.b    58-24,'Sequencer loaded user music.score',10,0
  1266.     even
  1267. five:    dc.b    43-24,'Sequencer is happy',10,0
  1268.     even
  1269. six:    dc.b    54-24,'Sequencer saved "music.score"',10,0
  1270.     even
  1271. seven:    dc.b    60-24,'Sequencer looking for "music.score"',10,0
  1272.     end
  1273.  
  1274. ; end of tetrissound.s
  1275.